package com.lzx.answer.controller.web;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.lzx.answer.entity.Problem;
import com.lzx.answer.entity.vo.NicknameVO;
import com.lzx.answer.entity.vo.OssVO;
import com.lzx.answer.entity.vo.UploadProblem;
import com.lzx.answer.service.BrowseService;
import com.lzx.answer.service.ProblemService;
import com.lzx.common.utils.R;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/answer/problem/web")
public class WebProblemController {
    @Resource
    private ProblemService problemService;

    @Resource
    private BrowseService browseService;

    //获取浏览量最多的十个问答
    @GetMapping("/getTopTenProblem")
    public R getTopTenProblem() {
        return problemService.getTopTenProblem();
    }

    //获取问答总数
    @GetMapping("/getProblemTotal")
    public Map<String, Integer> getProblemTotal() {
        Map<String, Integer> map = new HashMap<>();
        map.put("browseNum", Math.toIntExact(browseService.count()));
        map.put("problemNum", Math.toIntExact(problemService.count()));
        return map;
    }

    //用户修改头像或昵称 es同步
    @GetMapping("/getUserProblemListToES/{userId}")
    public List<Problem> getUserArticleListToES(@PathVariable Long userId) {
        return problemService.getUserProblemListToES(userId);
    }

    //修改用户昵称(问题)
    @PutMapping("/updateNicknameToProblem")
    public String updateNicknameToProblem(@RequestBody NicknameVO nicknameVO) {
        return problemService.updateNicknameToProblem(nicknameVO);
    }

    //修改用户头像(问题)
    @PutMapping("/updateAvatarToProblem")
    public String updateAvatarToProblem(@RequestBody OssVO ossVO) {
        return problemService.updateAvatarToProblem(ossVO);
    }

    //根据id查询问题
    @GetMapping("/getProblem/{problemId}")
    public Problem getProblem(@PathVariable int problemId) {
        return problemService.getById(problemId);
    }

    //获取当前用户发表的问题
    @GetMapping("/getProblemListByUserId/{userId}")
    public R getProblemListByUserId(@PathVariable Long userId) {
        return problemService.getProblemListByUserId(userId);
    }

    //获取当前用户关注的人发表的问题
    @GetMapping("/getUserAttentionPublishProblem/{userIds}")
    public List<Problem> getUserAttentionPublishProblem(@PathVariable List<Integer> userIds) {
        return problemService.getUserAttentionPublishProblem(userIds);
    }

    //上传问题的用户是否解决问题(用户个人中心页面)
    @PutMapping("/isSolveProblem/{userId}/{problemId}")
    public R isSolveProblem(@PathVariable Long userId, @PathVariable Long problemId) {
        return problemService.isSolveProblem(userId, problemId);
    }

    //TODO 统计作者的回答数、文章数
    @GetMapping("/statistical/{userId}")
    public R statistical(@PathVariable Long userId) {
        return problemService.statistical(userId);
    }

    //根据点赞数查询前十条问题
    @GetMapping("/rankBeforeTen")
    public R rankBeforeTen() {
        return problemService.rankBeforeTen();
    }

    //根据问题id获取问题信息
    @GetMapping("/{id}")
    public R getProblemById(@PathVariable Long id) {
        return problemService.getProblemById(id);
    }

    //上传问题
    @PostMapping("/upload")
    public R upload(@RequestBody UploadProblem uploadProblem) {
        return problemService.upload(uploadProblem);
    }

    /**
     * @Cacheable 开启缓存功能
     * Cacheable：如果缓存中存在则不缓存，如果不存在则缓存
     * #root.method.name将方法名作为key(即getList)
     * sync = true 加锁，解决缓存击穿
     */
    //获取所有问题
    @GetMapping("/getList/{current}/{size}")
//    @Cacheable(value = {"problem"}, key = "#root.method.name", sync = true)
    @SentinelResource(value = "getList", blockHandler = "xl", fallback = "ldq")
    public R getList(@PathVariable int current, @PathVariable int size) {
        return problemService.getList(current, size);
    }

    //获取所有问题给es服务
    @GetMapping("/getProblemListToES")
    public List<Problem> getProblemListToES() {
        return problemService.list();
    }

    // 这里的返回值要和方法的返回值类型一样 如下面方法应该返回R
    // 服务流量控制处理 限流
    public R xl(BlockException exception) {
        return R.error().data("异常为", exception.getMessage()).message("服务异常");
    }

    // 服务熔断降级处理 熔断器
    public R ldq(BlockException exception) {
        return R.error().data("异常为", exception.getMessage()).message("服务不可用");
    }
}
